package com.ai.aspect;

import com.ai.common.cache.TimeExpiredPoolCache;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Random;

/**
 * @author ：shengwenyang
 * @date ：Created in 2023/5/29 16:31
 * @description：
 * @version:
 */
@Aspect
@Slf4j
@Order(1000)
@Component
public class CacheServiceAspect {

    @Pointcut("@annotation(com.ai.aspect.CacheService)")
    public void aspect() {}

    @Around("aspect()")
    public Object execute(ProceedingJoinPoint point) throws Throwable {
        Object result = null;
//        String test1 = "[{\"contentType\":\"a\",\"text\":\"测试11\"},{\"contentType\":\"b\",\"text\":\"测试22\"}]";
//        String test2 = "[{\"id\":\"1\",\"title\":\"标题1\",\"text\":\"测试1\"},{\"id\":\"2\",\"title\":\"标题2\",\"text\":\"测试2\"}]";
        String className = point.getSignature().getDeclaringType().getSimpleName();
        //参数列表
        Object[] args = point.getArgs();
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        Method method = methodSignature.getMethod();
        String methodName = method.getName();
        //获取缓存key
        String cacheKey = getCacheKey(className + "." + methodName,args);

        Object responseCache = TimeExpiredPoolCache.getInstance().get(cacheKey);
        if (responseCache != null){
            return responseCache;
        }

//        CacheService bean = method.getAnnotation(CacheService.class);
//        String key = bean.getKey();
//        if (key.equals("cache1")) {
//            result = buildResult(method, test1);
//        }else{
//            result = buildResult(method, test2);
//        }

        result = point.proceed();
        //获取指定范围随机数
        int min = 1;
        int max = 30;
        Random random = new Random();
        int randomNumber = random.nextInt(max - min + 1) + min;
        //1.5分钟左右缓存
        TimeExpiredPoolCache.getInstance().put(cacheKey,result,(60 + randomNumber)*1000L);
        return result;
    }
    public static String getCacheKey(String methodName,Object[] args) throws Exception {
        if (args == null || args.length == 0){
            return methodName;
        }
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(methodName);
        for (Object arg : args) {
            if (arg != null) {
                Class<?> aClass = arg.getClass();
                if (aClass == String.class || aClass == Long.class || aClass == Integer.class || aClass == Double.class || aClass == Float.class || aClass == Boolean.class){
                    stringBuffer.append("-").append(arg);
                }else if (aClass == List.class){
                    continue;
                }else{
                    Field[] fields = aClass.getDeclaredFields();
                    for (Field field : fields) {
                        field.setAccessible(true);
                        Object value = field.get(arg);
                        stringBuffer.append("-").append(value);
                        //System.out.println(field.getName() + " = " + value);
                    }
                }
            }
        }
        return stringBuffer.toString();
    }

    /**
     * 把string转换成指定的类型
     */

    public static Object buildResult(Method method, String result) throws Exception {
        if (method.getReturnType() == String.class) {
            return result;
        } else if (method.getReturnType() == Long.class) {
            return Long.parseLong(result);
        } else if (method.getReturnType() == Integer.class) {
            return Integer.parseInt(result);
        } else if (method.getReturnType() == Double.class) {
            return Double.parseDouble(result);
        } else if (method.getReturnType() == Float.class) {
            return Float.parseFloat(result);
        } else if (method.getReturnType() == List.class) {
            return JSON.parseArray(result, getReturnTypeClazz(method));
        } else {
            return JSON.parseObject(result, getReturnTypeClazz(method));
        }
    }

    protected static Class getReturnTypeClazz(Method method) {
        if (method.getReturnType() == List.class) {
            return (Class) ((ParameterizedType) method.getGenericReturnType()).getActualTypeArguments()[0];
        }
        return method.getReturnType();
    }
}
